'use client';

import { useInfiniteQuery } from '@tanstack/react-query';
import { clientQuerySectionDetailsById } from '@/services/api';
import type { IPost, ISectionDetails } from '@/interfaces';
import Link from 'next/link';
import classNames from 'classnames';
import { formatCount, toRelativeTime } from '@/lib/tool';
import { useContext, useEffect, useState } from 'react';
import useToast from '@/hooks/useToast';
import Nodata from '@/app/[locale]/common/nodata/nodata';
import PostName from '@/app/[locale]/common/post/name';
import ContentHtml from '@/app/[locale]/common/content/html';
import type { ISectionIdPageContext } from '@/contexts/section-id';
import { SectionIdPageContext } from '@/contexts/section-id';
import PcBox from '@/app/[locale]/common/other/pc';
import Spinner from '@/app/[locale]/component/spinner/spinner';
import H5Box from '@/app/[locale]/common/other/h5';
import SectionIdH5Page from '@/app/[locale]/sections/[id]/h5';

export default function SectionIdPage({
  source,
  translatedFields,
}: ISectionIdPageContext) {
  const { show } = useToast();
  const [pages, setPages] = useState<IPost[]>(
    source.sectionDetails.data!.content,
  );

  const clientQuerySectionDetailsByIdQuery = useInfiniteQuery(
    [
      '/forum',
      '/sections',
      '/client',
      source.sectionDetails.basic.id,
      '/details',
      'infinite',
    ],
    async (context) => {
      return (await clientQuerySectionDetailsById({
        id: context.queryKey[3],
        query: context.pageParam,
      })) as ISectionDetails;
    },
    {
      keepPreviousData: true,
      getPreviousPageParam: (firstPage) => {
        if (!firstPage.data!.pageable.previous) {
          return;
        }
        return {
          page: Math.max(firstPage.data!.pageable.page - 1, 0),
        };
      },
      getNextPageParam: (lastPage) => {
        if (!lastPage.data!.pageable.next) {
          return;
        }
        return {
          page: Math.min(
            lastPage.data!.pageable.page + 1,
            lastPage.data!.pageable.pages,
          ),
        };
      },
      initialData: () => {
        return {
          pages: [source.sectionDetails],
          pageParams: [{ page: 0 }],
        };
      },
    },
  );

  useEffect(() => {
    if (clientQuerySectionDetailsByIdQuery.data) {
      setPages(
        clientQuerySectionDetailsByIdQuery.data.pages
          .flatMap((item) => item.data!.content)
          .map((item) => {
            item._contentUpdatedOnText = toRelativeTime(item.contentUpdatedOn);
            return item;
          }),
      );
    }
  }, [clientQuerySectionDetailsByIdQuery.data]);

  async function onClickLoadMore() {
    try {
      await clientQuerySectionDetailsByIdQuery.fetchNextPage();
    } catch (e) {
      show({
        type: 'DANGER',
        message: e,
      });
    }
  }

  return (
    <SectionIdPageContext.Provider value={{ source, translatedFields }}>
      <PcBox classs="col px-2 py-4">
        <Top />
        <div className="mt-2 card border-0">
          <div className="card-body vstack gap-4">
            <TagGroups />

            <Tags />

            {pages.length > 0 && (
              <>
                <Posts pages={pages} />

                <LoadMoreBtn
                  isLoading={clientQuerySectionDetailsByIdQuery.isLoading}
                  onClickLoadMore={onClickLoadMore}
                />
              </>
            )}

            {pages.length === 0 && <Nodata />}
          </div>
        </div>
      </PcBox>

      <H5Box classs="col px-2 py-4">
        <SectionIdH5Page />
      </H5Box>
    </SectionIdPageContext.Provider>
  );
}

const Top = () => {
  const {
    source: { sectionDetails },
    translatedFields,
  } = useContext(SectionIdPageContext)!;
  const name = sectionDetails.basic.name;
  const content = sectionDetails.content;
  const admins = sectionDetails.admins;

  return (
    <div className="card border-0">
      <div className="card-body">
        <h1
          className="fs-4 card-title d-flex align-items-center mb-4"
          title={name}
        >
          <span>{name}</span>
        </h1>

        <ContentHtml content={content} />

        <div className="card-subtitle d-flex justify-content-end text-secondary mt-4">
          {admins.map((item, index) => {
            return (
              <div key={item.id}>
                <Link
                  href={`/users/${item.id}`}
                  className="link-body-emphasis link-offset-3 link-underline-opacity-0 link-underline-opacity-100-hover"
                >
                  {item.alias}
                </Link>
                {index !== admins.length - 1 && '、'}
              </div>
            );
          })}
        </div>
        <p className="text-end card-text text-secondary">
          {translatedFields.admin}
        </p>
      </div>
    </div>
  );
};

const TagGroups = () => {
  const {
    source: {
      sectionDetails,
      queryParams: { tagId, tagGroupId },
    },
    translatedFields,
  } = useContext(SectionIdPageContext)!;
  const id = sectionDetails.basic.id;
  const tagGroups = sectionDetails.tagGroups ?? [];

  return (
    <>
      {tagGroups.length > 0 && (
        <>
          {tagGroups.map((tagGroupItem) => {
            return (
              <div key={tagGroupItem.id} className="hstack gap-3 mb-3">
                <Link
                  href={`/sections/${id}`}
                  className="badge fw-normal fs-6 link-body-emphasis link-offset-3 link-underline-opacity-0 link-underline-opacity-100-hover"
                >
                  {tagGroupItem.name}
                </Link>

                {(tagGroupItem.tags || []).map((tagItem) => {
                  return (
                    <Link
                      key={tagItem.id}
                      href={`/sections/${id}?tid=${tagItem.id}&tgid=${tagGroupItem.id}`}
                      className={classNames(
                        'badge fw-normal fs-6 link-body-emphasis link-offset-3 link-underline-opacity-0 link-underline-opacity-100-hover',
                        {
                          'bg-secondary text-light':
                            tagGroupId === tagGroupItem.id + '' &&
                            tagId === tagItem.id + '',
                        },
                      )}
                    >
                      {tagItem.name}
                    </Link>
                  );
                })}
              </div>
            );
          })}
        </>
      )}
    </>
  );
};

const Tags = () => {
  const {
    source: {
      sectionDetails,
      queryParams: { tagId },
    },
    translatedFields,
  } = useContext(SectionIdPageContext)!;
  const id = sectionDetails.basic.id;
  const tags = sectionDetails.tags ?? [];

  return (
    <div className="hstack gap-3">
      <Link
        href={`/sections/${id}`}
        className="badge fw-normal fs-6 link-body-emphasis link-offset-3 link-underline-opacity-0 link-underline-opacity-100-hover"
      >
        {translatedFields.all}
      </Link>

      {tags.map((item) => {
        return (
          <Link
            key={item.id}
            href={`/sections/${id}?tid=${item.id}`}
            className={classNames(
              'badge fw-normal fs-6 link-body-emphasis link-offset-3 link-underline-opacity-0 link-underline-opacity-100-hover',
              {
                'bg-secondary text-light': tagId === item.id + '',
              },
            )}
          >
            {item.name}
          </Link>
        );
      })}
    </div>
  );
};

const Posts = ({ pages }: { pages: IPost[] }) => {
  const { translatedFields } = useContext(SectionIdPageContext)!;

  return (
    <div className="table-responsive mt-5 mb-4">
      <table className="table table-hover table-borderless align-middle text-nowrap text-center">
        <thead>
          <tr className="align-middle">
            <th scope="col" className="fw-normal">
              {translatedFields.title}
            </th>
            <th scope="col" className="fw-normal">
              {translatedFields.comments}
            </th>
            <th scope="col" className="fw-normal">
              {translatedFields.replies}
            </th>
            <th scope="col" className="fw-normal">
              {translatedFields.views}
            </th>
            <th scope="col" className="fw-normal">
              {translatedFields.created}
            </th>
            <th scope="col" className="fw-normal">
              {translatedFields.time}
            </th>
          </tr>
        </thead>
        <tbody>
          {pages.map((item) => {
            return (
              <tr key={item.id} className="align-middle">
                <td className="text-nowrap text-md-wrap">
                  <PostName
                    item={item}
                    isTable
                    isJustifyContentCenter
                    isFwSemibold={false}
                  />
                </td>

                <td>{formatCount(item.details!.commentCount)}</td>

                <td>{formatCount(item.details!.replyCount)}</td>

                <td>{formatCount(item.details!.viewCount)}</td>

                <td>
                  <Link
                    href={`/users/${item.createdBy}`}
                    className="text-reset link-underline link-offset-3 link-underline-opacity-0 link-underline-opacity-100-hover"
                  >
                    {item.creatorAlias}
                  </Link>
                </td>

                <td>
                  <time dateTime={item.contentUpdatedOn}>
                    {item._contentUpdatedOnText}
                  </time>
                </td>
              </tr>
            );
          })}
        </tbody>
      </table>
    </div>
  );
};

const LoadMoreBtn = ({
  onClickLoadMore,
  isLoading,
}: {
  onClickLoadMore: () => void;
  isLoading: boolean;
}) => {
  return (
    <div className="row mt-4 mb-3">
      <div className="col">
        <button
          onClick={onClickLoadMore}
          disabled={isLoading}
          type="button"
          className="btn rounded-pill text-secondary-emphasis w-100"
        >
          {isLoading ? <Spinner /> : <i className="bi bi-three-dots"></i>}
        </button>
      </div>
    </div>
  );
};
